package com.yang.core.config;

import com.yang.core.extension.ExtensionRegistry;
import com.yang.core.api.RestClient;
import com.yang.core.api.RestClientBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;

/**
 * RestClient自动配置类
 * 实现开箱即用的自动配置功能
 */
@Slf4j
@AutoConfiguration
@ConditionalOnClass(RestClient.class)
@EnableConfigurationProperties(RestClientProperties.class)
public class RestClientAutoConfiguration {

    private final RestClientProperties properties;

    public RestClientAutoConfiguration(RestClientProperties properties) {
        this.properties = properties;
    }

    /**
     * 初始化扩展注册中心
     */
    @PostConstruct
    public void initializeExtensions() {
        if (properties.getBasic().isAutoDiscovery()) {
            log.info("RestClient: 开始自动发现扩展");
            ExtensionRegistry.autoDiscoverExtensions();
            ExtensionRegistry.initializeAll();

            // 打印扩展统计信息
            var stats = ExtensionRegistry.getStatistics();
            log.info("RestClient: 扩展初始化完成，共加载 {} 个扩展", stats.get("totalExtensions"));
        }
    }

    /**
     * 销毁扩展注册中心
     */
    @PreDestroy
    public void destroyExtensions() {
        log.info("RestClient: 开始销毁扩展");
        ExtensionRegistry.destroyAll();
    }

    /**
     * 创建默认RestClient构建器
     */
    @Bean
    @ConditionalOnMissingBean
    public RestClientBuilder restClientBuilder() {
        log.info("RestClient: 创建默认RestClient构建器");

        RestClientBuilder builder = RestClient.builder()
                .baseUrl(properties.getBasic().getBaseUrl())
                .userAgent(properties.getBasic().getUserAgent())
                .charset(properties.getBasic().getCharset())
                .followRedirects(properties.getBasic().isFollowRedirects());

        // 配置超时
        builder.connectTimeout(properties.getTimeout().getConnect())
                .socketTimeout(properties.getTimeout().getSocket())
                .requestTimeout(properties.getTimeout().getRequest());

        // 配置默认请求头
        properties.getBasic().getDefaultHeaders().forEach(builder::defaultHeader);

        // 配置重试
        if (properties.getRetry().isEnabled()) {
            builder.enableRetry(true)
                    .maxRetries(properties.getRetry().getMaxAttempts())
                    .retryDelay(properties.getRetry().getInitialDelay())
                    .retryBackoffMultiplier(properties.getRetry().getBackoffMultiplier())
                    .maxRetryDelay(properties.getRetry().getMaxDelay());
        }

        // 配置连接池
        builder.maxConnectionsTotal(properties.getPool().getMaxTotal())
                .maxConnectionsPerRoute(properties.getPool().getMaxPerRoute())
                .connectionTTL(properties.getPool().getTimeToLive())
                .validateAfterInactivity(properties.getPool().getValidateAfterInactivity());

        // 配置代理
        if (properties.getProxy().isEnabled()) {
            builder.proxyHost(properties.getProxy().getHost())
                    .proxyPort(properties.getProxy().getPort())
                    .proxyCredentials(properties.getProxy().getUsername(), properties.getProxy().getPassword());
        }

        // 配置SSL
        if (properties.getSsl().isTrustAll()) {
            builder.trustAllCertificates(true);
        }
        builder.hostnameVerification(properties.getSsl().isHostnameVerification());

        // 配置压缩
        if (properties.getCompression().isEnabled()) {
            builder.enableCompression(true);
        }

        // 应用所有扩展
        applyExtensions(builder);

        return builder;
    }

    /**
     * 创建默认RestClient实例
     */
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(name = "restclient.default.enabled", havingValue = "true", matchIfMissing = true)
    public RestClient defaultRestClient(RestClientBuilder builder) {
        log.info("RestClient: 创建默认RestClient实例");
        return builder.build();
    }

    /**
     * 应用所有扩展到构建器
     */
    private void applyExtensions(RestClientBuilder builder) {
        ExtensionRegistry.getAllExtensions().forEach(extension -> {
            try {
                extension.extend(builder);
                log.debug("RestClient: 应用扩展 {}", extension.getName());
            } catch (Exception e) {
                log.error("RestClient: 应用扩展失败: {}", extension.getName(), e);
            }
        });
    }

    /**
     * 配置类 - 监控相关
     */
    @Configuration
    @ConditionalOnProperty(name = "restclient.monitoring.enabled", havingValue = "true", matchIfMissing = true)
    static class MonitoringConfiguration {

        @Bean
        @ConditionalOnMissingBean
        public RestClientMonitoringInterceptor monitoringInterceptor(RestClientProperties properties) {
            return new RestClientMonitoringInterceptor(properties.getMonitoring());
        }
    }

    /**
     * 配置类 - 缓存相关
     */
    @Configuration
    @ConditionalOnProperty(name = "restclient.cache.enabled", havingValue = "true")
    static class CacheConfiguration {

        @Bean
        @ConditionalOnMissingBean
        public RestClientCacheInterceptor cacheInterceptor(RestClientProperties properties) {
            return new RestClientCacheInterceptor(properties.getCache());
        }
    }

    /**
     * 配置类 - 认证相关
     */
    @Configuration
    @ConditionalOnProperty(name = "restclient.auth.type", havingValue = "oauth2")
    static class OAuth2Configuration {

        @Bean
        @ConditionalOnMissingBean
        public OAuth2AuthenticationInterceptor oauth2Interceptor(RestClientProperties properties) {
            return new OAuth2AuthenticationInterceptor(properties.getAuth().getOauth2());
        }
    }
}